#ifndef __M_DB_H__
#define __M_DB_H__
#include "Util.hpp"
#include <mutex>
#include <cassert>
class user_table
{
public:
    user_table(const std::string &host,
               const std::string &username,
               const std::string &password,
               const std::string &dbname,
               int port)
    {
        mysql = mysql_util::mysql_create(host, username, password, dbname, port);
        assert(mysql != nullptr);
    }
    bool insert(const Json::Value &user)
    {
#define INSERT_USER "insert into user values(null, '%s', MD5('%s'), 1000, 0, 0);"
        char sqlbuf[1024] = {0};
        sprintf(sqlbuf, INSERT_USER, user["username"].asCString(), user["password"].asCString());
        if (mysql_util::mysql_execute(mysql, sqlbuf) == false)
        {
            ELOG("insert user failed username: %s password: %s", user["username"].asCString(), user["password"].asCString());
            return false;
        }
        return true;
    }
    bool login(Json::Value &user)
    {
#define LOGIN_USER "select id, score, total_count, win_count from user where username='%s' and password=MD5('%s');"
        char sqlbuf[1024] = {0};
        sprintf(sqlbuf, LOGIN_USER, user["username"].asCString(), user["password"].asCString());
        if (mysql_util::mysql_execute(mysql, sqlbuf) == false)
        {
            ELOG("login error");
            return false;
        }
        MYSQL_RES* res = mysql_store_result(mysql);
        int row_num = mysql_num_rows(res);
        if (row_num != 1)
        {
            ELOG("user is not exists");
            return false;
        }
        MYSQL_ROW row = mysql_fetch_row(res);
        user["id"] = row[0];
        user["score"] = row[1];
        user["total_count"] = row[2];
        user["win_count"] = row[3];
        mysql_free_result(res);
        return true;
    }
    bool get_userinfo_by_name(const std::string username, Json::Value &user)
    {
#define USER_BY_NAME "select id, score, total_count, win_count from user where username='%s';"
        char sqlbuf[1024] = {0};
        sprintf(sqlbuf, USER_BY_NAME, username.c_str());
        if (mysql_util::mysql_execute(mysql, sqlbuf) == false)
        {
            ELOG("get_userinfo_by_name failed");
            return false;
        }
        // 保存结果到本地
        MYSQL_RES *res = mysql_store_result(mysql);
        // 获取结果行数
        int row_num = mysql_num_rows(res);
        if (row_num != 1)
        {
            ELOG("userinfo is not exists");
            return false;
        }
        // 处理结果
        MYSQL_ROW row = mysql_fetch_row(res);
        user["username"] = username.c_str();
        user["id"] = row[0];
        user["score"] = row[1];
        user["total_count"] = row[2];
        user["win_count"] = row[3];
        // 释放结果集
        mysql_free_result(res);
        return true;
    }
    bool get_userinfo_by_id(int id, Json::Value& user)
    {
#define USER_BY_ID "select username, score, total_count, win_count from user where id=%d;"
        char sqlbuf[2014] = {0};
        sprintf(sqlbuf, USER_BY_ID, id);
        if (mysql_util::mysql_execute(mysql, sqlbuf) == false)
        {
            ELOG("get_userinfo_by_id failed");
            return false;
        }
        // 保存结果到本地
        MYSQL_RES *res = mysql_store_result(mysql);
        // 获取结果的行数
        int row_num = mysql_num_rows(res);
        if (row_num != 1)
        {
            ELOG("userinfo is not exists");
            return false;
        }
        // 处理结果
        MYSQL_ROW row = mysql_fetch_row(res);
        user["id"] = id;
        user["username"] = row[0];
        user["score"] = row[1];
        user["total_count"] = row[2];
        user["win_count"] = row[3];
        // 释放结果集
        mysql_free_result(res);
        return true;
    }
    bool win(int id)
    {
#define USER_WIN "update user set score=score+30, total_count=total_count+1, win_count=win_count+1 where id=%d;"
        char sqlbuf[1024] = {0};
        sprintf(sqlbuf, USER_WIN, id);
        if (mysql_util::mysql_execute(mysql, sqlbuf) == false)
        {
            ELOG("update wininfo failed");
            return false;
        }
        return true;
    } 
    bool loss(int id)
    {
#define USER_LOSS "update user set score=score-30, total_count=total_count+1 where id=%d;"
        char sqlbuf[1024] = {0};
        sprintf(sqlbuf, USER_LOSS, id);
        if (mysql_util::mysql_execute(mysql, sqlbuf) == false)
        {
            ELOG("update lossinfo failed");
            return false;
        }
        return true;
    }
    ~user_table()
    {
        mysql_close(mysql);
    }

private:
    MYSQL *mysql;
    std::mutex _mutex;
};

#endif
